﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace Mines.Ajax
{
    public class AjaxHttpModule : IHttpModule
    {
        public void Init(HttpApplication context)
        {
            context.BeginRequest += new EventHandler(context_BeginRequest);
        }
        void context_BeginRequest(object sender, EventArgs e)
        {
            HttpApplication application = (HttpApplication)sender;
            HttpContext context = application.Context;
            var path = context.Request.Url.AbsolutePath.ToLower();
            if (path.StartsWith("/ajax/") && path.EndsWith(".ashx"))
            {
                try
                {
                    var alias = System.IO.Path.GetFileName(context.Request.Path);

                    alias = alias.Substring(0, alias.IndexOf('.'));

                    var ajaxModel = Common.ajaxModels.Where((m) => m.Alias == alias).FirstOrDefault();

                    Exception ex;
                    if (ajaxModel == null)
                    {
                        ex = new AjaxTypeNullException();
                        throw ex;
                    }

                    var methodName = context.Request.Headers["method"];

                    if (!string.IsNullOrEmpty(methodName))
                    {
                        byte[] byts = new byte[context.Request.InputStream.Length];
                        context.Request.InputStream.Read(byts, 0, byts.Length);
                        string req = System.Text.Encoding.UTF8.GetString(byts);

                        var args = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(req);

                        var d = string.Empty;
                        foreach (var k in args.Keys)
                            d += k + ",";
                        
                        d = d.Trim(',');


                        var method = ajaxModel.Methods.Where((m) => m.Name == methodName && m.ParamNames == d).SingleOrDefault();

                        if (method == null)
                        {
                            ex = new AjaxArgumentsException();
                            throw ex;
                        }

                        var ptypes = new List<object>();

                        try
                        {
                            object arg = null;
                            for (var i = 0; i < method.Parameters.Length; i++)
                            {
                                arg = args[method.Parameters[i].Name];
                                if (arg == null || string.IsNullOrEmpty(arg.ToString()) || arg.ToString().ToLower() == "null")
                                    ptypes.Add(null);
                                else
                                {
                                    if (method.Parameters[i].ParameterType == arg.GetType())
                                        ptypes.Add(arg);
                                    else
                                    {
                                        var pi = Newtonsoft.Json.JsonConvert.DeserializeObject(Newtonsoft.Json.JsonConvert.SerializeObject(arg), method.Parameters[i].ParameterType);
                                        ptypes.Add(pi);
                                    }
                                }
                            }
                        }
                        catch (Exception ex1)
                        {
                            throw ex1;
                        }
                        switch (method.SessionState)
                        {
                            case SessionState.ReadOnly:
                                context.RemapHandler(new AjaxReadOnlySessionHandler(ajaxModel.Type, method, ptypes.ToArray()));
                                break;
                            case SessionState.ReadAndWrite:
                                context.RemapHandler(new AjaxRequiresSessionHandler(ajaxModel.Type, method, ptypes.ToArray()));
                                break;
                            default:
                                context.RemapHandler(new AjaxNoneSessionHandler(ajaxModel.Type, method, ptypes.ToArray()));
                                break;
                        }
                    }
                    else
                    {
                        context.RemapHandler(new InitHttpHandler(ajaxModel));
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.WriteErrorLog(this.GetType(), ex);
                    context.Response.Write(Newtonsoft.Json.JsonConvert.SerializeObject(new { error = ex.Message }));

                }
            }
        }

        public void Dispose() { }
    }
}